package top.lishuoboy.spring.jdbc_template.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import top.lishuoboy.spring.jdbc_template.dao.UserDao;

@Slf4j
@Service
public class UserService {
    @Autowired
    private UserDao userDao;
    @Autowired
    DataSourceTransactionManager txManager;

    /**
     * 转账
     * 声明式事务管理。
     * 原理：通过 AOP 动态代理简化了 下面 transferMoneyCode() 编程式事务管理 的代码
     *
     * @param money 转账金额
     * @param inId  收款人Id
     * @param outId 付款人Id
     */
    // 注解在类上，对该类和子类的所有方法都开启事务
    @Transactional
    public void transferMoney(int money, int inId, int outId) {
        userDao.addMoney(money, inId);
        userDao.reduceMoney(money, outId);
    }

    /**
     * 转账
     * 编程式事务管理
     *
     * @param money 转账金额
     * @param inId  收款人Id
     * @param outId 付款人Id
     */
    public void transferMoneyCode(int money, int inId, int outId) {
        // 原理：内部封装了开启事务代码 conn.setAutoCommit(false); 并将该 conn 封装到 status 中
        TransactionStatus status = txManager.getTransaction(new DefaultTransactionDefinition());
//        log.warn("status=={}", HuJsonUtil.toJsonPrettyStr(status));

        try {
            userDao.addMoney(money, inId);
            userDao.reduceMoney(money, outId);
            // 原理：内部封装了 status.getConn.commit();
            txManager.commit(status);
        } catch (Exception e) {
            txManager.rollback(status);
            log.error("转账异常", e);
        }
    }
}